use std::io;
use thiserror::Error;

use crate::{http::{HttpReceiveError, HttpRequestBuildError, HttpSendError}, websockt::{WebSocketReceiveError, WebSocketSendError}};

#[derive(Debug, Error)]
pub enum ClientError {
    #[error("Failed to build HTTP request: {0}")]
    BuildHttpRequest(#[from] ClientBuildHttpRequest),

    #[error("Invalid web socket upgrad: {0}")]
    InvalidWebSocketUpgrade(String),

    #[error("Connection closed unexpectedly")]
    ConnectionClosed,

    #[error("Failed to receive a http request: {0}")]
    HttpReceive(#[from] HttpReceiveError),

    #[error("Failed to send a http response: {0}")]
    HttpSend(#[from] HttpSendError),

    #[error("Failed to receive a websocket frame: {0}")]
    WebSocketReceive(#[from] WebSocketReceiveError),

    #[error("Failed to send a websocket frame: {0}")]
    WebSocketSend(#[from] WebSocketSendError),

    #[error("I/O error during read/write: {0}")]
    IoError(#[from] io::Error),
}

#[derive(Debug, Error)]
pub enum ClientBuildHttpRequest {
    #[error("Failed to build HTTP request: {0}")]
    Build(#[from] HttpRequestBuildError),

    #[error("Missing required Host header")]
    MissingHost,

    #[error("Failed to parse headers: {0}")]
    InvalidHeaders(String),
}

impl From<HttpRequestBuildError> for ClientError  {
    fn from(value: HttpRequestBuildError) -> Self {
        Self::BuildHttpRequest(ClientBuildHttpRequest::Build(value))
    }
}